/**************************************************************************************
*
*	Copyright (C) 2010 Brent Andrew O. Chua - See LICENSE.txt for more info.
*		
*	Filename	-	VertexBuffer.cpp
*
*	Comments	-	See VertexBuffer.h
*
**************************************************************************************/

#ifdef __PSX_WINDOWS_WINDOW

#include "../Include/VertexBuffer.h"
#include "../Include/GraphicsTypes.h"
#include "../Include/Renderer.h"
#include "../Include/DX9Mapping.h"

#include <d3d9.h>

namespace Pulse
{
	VertexBuffer::VertexBuffer( void )
		: m_pDevice( NULL ), m_pVB( NULL )
	{

	}
	
	VertexBuffer::VertexBuffer( VertexBufferDescription *pDesc )
		: m_desc( *pDesc ), m_pDevice( NULL ), m_pVB( NULL )
	{

	}
	
	VertexBuffer::~VertexBuffer( void )
	{
		Cleanup();
	}

	BOOL VertexBuffer::CreateResource( void )
	{
		if ( IsResourceCreated() )
		{
			PSX_PushWarning( "Resource has already been created." );
			return FALSE;
		}

		SetFlagCreated();
		return TRUE;
	}

	BOOL VertexBuffer::DestroyResource( void )
	{
		if ( IsResourceCreated() )
		{
			DisableResource();
			Cleanup();
			SetFlagUnloaded();
			SetFlagDestroyed();
		}

		return TRUE;
	}

	BOOL VertexBuffer::DisableResource( void )
	{
		if ( !IsResourceCreated() )
		{
			PSX_PushWarning( "Resource has not been created." );
			return FALSE;
		}

		SetFlagDisabled();
		return TRUE;
	}

	BOOL VertexBuffer::RestoreResource( void )
	{
		if ( !IsResourceCreated() )
		{
			PSX_PushWarning( "Resource has not been created." );
			return FALSE;
		}

		SetFlagRestored();
		return TRUE;
	}

	BOOL VertexBuffer::LoadResource( const CHAR *pFilename )
	{
		return FALSE;
	}
	
	BOOL VertexBuffer::SaveResource( const CHAR *pFilename )
	{
		return FALSE;
	}

	EErrorCode::Type VertexBuffer::Initialize( void )
	{
		Cleanup();

		DWORD usage = 0;
		D3DPOOL pool = D3DPOOL_MANAGED;

		if ( m_desc.bufferType == EVertexBufferType::DYNAMIC )
		{
			usage = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
			pool = D3DPOOL_DEFAULT;
		}

		// Create DX9 vertex buffer
		m_pDevice = (IDirect3DDevice9*)Renderer::GetInstance()->GetDevice()->GetDevice();

		HRESULT hr;
		if ( FAILED( hr = m_pDevice->CreateVertexBuffer( m_desc.numVertices * m_desc.vertexSize, usage,
			0, pool, &m_pVB, NULL ) ) )
		{
			PSX_PushError( "Failed to create DX9 Vertex buffer. %s", DX9Mapping::GetDXErrorDescription( hr ) );
			return EErrorCode::GRAPHICS;
		}

		return EErrorCode::NONE;
	}

	void VertexBuffer::Cleanup( void )
	{
		PSX_SafeRelease( m_pVB );
	}

	void VertexBuffer::Lock( POS_T start, SIZE_T count, void **pVertices )
	{
		DWORD lock = 0;

		if ( m_desc.bufferType == EVertexBufferType::DYNAMIC )
			lock = m_desc.bDiscardData ? D3DLOCK_DISCARD : D3DLOCK_NOOVERWRITE;

		m_pVB->Lock( start, count * m_desc.vertexSize, pVertices, lock );
	}

	void VertexBuffer::Unlock( void )
	{
		m_pVB->Unlock();
	}

	void VertexBuffer::Bind( void )
	{
		m_pDevice->SetStreamSource( m_streamIndex, m_pVB, 0, m_desc.vertexSize );
	}

	void VertexBuffer::Render( void )
	{
		m_pDevice->DrawPrimitive( static_cast<D3DPRIMITIVETYPE>(m_desc.primitiveType), 0, m_desc.numPrimitives );
	}

}

#endif __PSX_WINDOWS_WINDOW
